El computador. Su lenguaje
( Publicado en Revista Creces, Mayo 1982 )

Acusado de falta de creatividad, exceso de servilismo y carencia de sentido común, el computador es sólo tan inteligente como la persona que lo programa. Aquí contamos en qué forma se llega a dialogar con este ingeniero de la electrónica y cómo podemos "ganar su confianza" para ayudar al progreso.

Para utilizar efectivamente un computador no se requieren conocimientos de electrónica, así como para manejar un automóvil no se necesita saber mucho de ingeniería mecánica. Es indudable que una formación sólida en matemáticas y electrónica optimizarán el provecho y el placer de trabajar con computadores, pero la carencia de tal formación no es obstáculo para un manejo operacional del computador que haga de él una herramienta utilísima en un laboratorio de investigación, en el control de un proceso industrial o en la facilitación de labores administrativas, de enseñanza o de documentación bibliográfica.

Por otra parte, el desarrollo de la industria electrónica en las últimas décadas ha producido el microcomputador, cuyo costo es sólo una fracción del de los minicomputadores de la generación anterior. Así, para adquirir y utilizar un computador hoy día no se necesita ni grandes sumas de dinero ni grandes conocimientos técnicos.


Procesamiento y costos

Cuando los computadores son grandes máquinas de alto costo, que requieren complicadas condiciones de instalación y personal calificado capaz de manejar sistemas operativos relativamente complejos, entonces el precio de "horas de computación" tiende a ser muy elevado. En tales condiciones el uso habitual de un computador se relaciona al procesamiento y almacenamiento masivo de datos. Por ejemplo, un investigador recolecta resultados en una serie de experimentos, quizás a lo largo de meses, tabula listas de datos y los entra al computador. En poco rato éste realiza cuanto análisis estadistico el investigador le solicite, entrega los resultados e incluso puede ofrecer elegantes gráficos. El usuario entonces ha hecho uso del computador por un período relativamente breve, compatible con el alto precio del tiempo de computación. Otras veces la utilidad del computador está dada no tanto por su habilidad para realizar cálculos complejos sino por su enorme capacidad de almacenar datos -habitualmente utilizando discos magnéticos - y poder obtener en forma expedita y ordenada cualquier información requerida. Encontramos ejemplos típicos de esto en áreas como contabilidad, investigación bibliográfica y manejo de inventarios.

El procesamiento masivo de datos es sin duda la gran área de aplicación de los computadores debido a su flexibilidad, rapidez y capacidad de memoria. En muchos casos específicos, un microcomputador puede sustituir a un computador pesado en estas tareas, con las ventajas de menor costo y más fácil acceso. Sin embargo, los computadores en general son extraordinariamente idóneos para otros dos tipos de labores: la recolección de datos y el control dinámico de un proceso (Fig.1). Tales tareas exigen, sin embargo, la dedicación exclusiva, o al menos prolongada, del computador. Es por lo tanto en estas aplicaciones donde el precio del sistema y el costo de operación pasan a ser factores críticos, y es entonces aquí donde la introducción del microcomputador abre perspectivas insospechadas.


Operativa

La automatización de la colecta de datos consiste en conectar el computador a instrumentos de medición (polígrafos, transductores, etc.) para que, conforme a un programa, "lea" directamente la variable de interés (voltaje, temperatura, presión, etc.). Esto puede ser particularmente útil cuando la frecuencia de muestreo requerida es muy alta (muestra cada algunos milisegundos) o muy baja (muestras espaciadas de procesos de muy larga duración). Los datos que el computador lee pueden ser procesados para generar nuevos resultados, probablemente condensando la información, y estos nuevos datos o las lecturas originales pueden ser almacenadas en discos. Esto es muy cómodo para el usuario pues sus datos están desde la partida en una forma que permite el procesamiento masivo antes referido, es decir, no necesita tabular y entrar los resultados manualmente.

En la automatización del control de procesos se va un paso más adelante: el computador monitorea una o más variables y, en función de ellas, toma decisiones y actúa sobre los componentes de un determinado sistema. Desde luego, podemos tener un computador (o un microcomputador) instalado al lado del sistema a controlar y conectado a él mediante cables para leer las señales de interés y para operar sobre los componentes que controla. Pero es posiblemente en esta área donde la miniaturización y abaratamiento de la microelectrónica alcanza sus efectos más espectaculares, pues un microprocesador ocupa tan poco espacio y consume tan poca energía que puede ser directamente incluido en el sistema o instrumento a controlar. Así, hoy los encontramos en máquinas de escribir para hacer tareas como encuadrar las líneas en ambos márgenes, o en el sistema de inyección de combustible en un automóvil para optimizar rendimiento y minimizar contaminación, o en innumerables ejemplos que van desde artefactos para el hogar hasta intrincado instrumental de investigación.

Este artículo pretende entusiasmar a usuarios potenciales al presentar un resumen de los principios elementales de la computación. En otro artículo se abordan los microcomputadores en particular y se esbozan las formas de interacción entre el microcomputador y otros instrumentos. No pretende presentar los computadores como entes míticos o mágicos. El que una tarea haya sido realizada con ayuda de un computador no garantiza que esté bien pensada, pues por definición un computador es sólo tan inteligente como la persona que lo programa. Sin embargo, aún careciendo de propiedades sobrenaturales, el computador sí puede multiplicar la eficacia y creatividad del usuario al liberarlo de tareas rutinarias y al permitirle realizar mediciones y análisis que sin su ayuda habrían sido impracticables.


Algoritmos, programas y lenguajes

Un concepto clave en computación es el de algoritmo: una secuencia de instrucciones precisas, inequívocas, que al cumplirse rigurosamente permiten solucionar cualquier forma particular de un problema general. Cada vez que sumamos con papel y lápiz, por ejemplo, aplicamos cuidadosamente - aunque sin pensarlo mucho- una serie de reglas como el escribir los sumandos de modo tal que las unidades, decenas, etc. queden en sus respectivas columnas; el empezar por la columna de las unidades e ir avanzando hacia la izquierda, el sumar la reserva de una columna a la adyacente, por nombrar sólo algunas. Las mismas reglas se aplican a cualquier caso particular de sumandos y siempre anticipamos confiadamente que el resultado será correcto. Si esta secuencia de operaciones las sistematizamos formalmente en un diagrama de flujo, hemos creado un algoritmo para que un ser humano sume con papel y lápiz (Fig. 2). Estas secuencias de instrucciones recuerdan a las recetas de cocina, pero éstas quizás no sean buenos ejemplos de algoritmos por cuanto son siempre casos particulares, es decir, siempre se va a utilizar un conjunto específico de ingredientes para ser sometidos a un procedimiento determinado. Por el contrario, un algoritmo no se limita a un caso específico: el algoritmo de suma es tan bueno para sumar 542 más 34 como para sumar 231 más 1678.

Si pensamos un poco, casi cualquier tarea, por más talento y experiencia que aparentemente requiera, puede en principio ser descompuesta y descrita como una secuencia de pasos elementales relativamente simples. Por ejemplo, es concebible que una persona que no ha visto jamás un automóvil en su vida salga manejando fluidamente si nosotros fuéramos capaces, por una parte, de explicar con exquisito detalle cada paso involucrado y a su vez el alumno de cumplir con absoluta precisión las instrucciones. (Entre paréntesis, una vez que uno se ha imaginado tal situación no es difícil imaginar que el alumno pueda reemplazarse por un microprocesador que sepa frenar frente a las luces rojas, señalizar al doblar, insultar a los choferes que cometen errores, etc.). Nuestro alumno no podría entender una instrucción del tipo "embrague y enganche en primera"; tal orden tendría que ser desglosada en términos y operaciones cuyo significado él supiera. En un cierto sentido, la forma de operar de un computador es semejante a la de este alumno imaginario.

Las instrucciones que un computador puede cumplir son limitadas y muy simples, pero las cumple con absoluta precisión siendo las posibilidades de error prácticamente nulas. Por estas dos características fundamentales: simpleza y confiabilidad, se ha dicho que las únicas gracias de un computador son su falta de creatividad y su exceso de servilismo (dos rasgos que suelen asociarse). La extrema simpleza de las instrucciones que un computador es capaz de cumplir hace que hasta tareas sumamente simples - sumar dos números u ordenar tres nombres alfabéticamente - deban descomponerse en una serie de instrucciones elementales. Estas aparentes limitaciones son sobrepasadas con creces por otras dos características de los computadores electrónicos: extraordinaria rapidez y gran capacidad de memoria. Literalmente un computador ejecuta cientos de miles de estas instrucciones elementales por segundo y puede almacenar miles de instrucciones y datos en su memoria. El tener entonces que trabajar con un repertorio limitado de instrucciones elementales no constituye problema para el computador, quizás incluso en esa simplicidad radica parte de su fuerza. Para el que sí constituye un problema es para el usuario, que tendría que detallar minuciosamente sus programas.


Los lenguajes

Ya veremos en que consisten en realidad estas instrucciones elementales que son las únicas que un computador propiamente puede entender. Recién entonces el lector podrá imaginar cuán penoso sería tener que escribir largos programas utilizando este repertorio de instrucciones llamado "código de máquina". Por fortuna rara vez un programador escribe directamente en código de máquina, habitualmente escribe en lenguajes "de alto nivel", como FORTRAN, COBOL, BASIC, PASCAL, etc. Estos lenguajes tienen por objeto evitarle al usuario la minuciosidad y detallismo que el código de máquina exige, y permitirle escribir usando instrucciones parecidas al simbolismo y convenciones del álgebra y a las palabras del idioma inglés. Una cantidad abrumadora de trabajo involucrado en escribir un programa en código de máquina se transforma así en una breve serie de instrucciones que globalizan los pasos elementales.

Podemos ilustrar la diferencia entre instrucciones de lenguaje de alto nivel e instrucciones de código de máquina con un ejemplo de la vida cotidiana. Supongamos que nos acercamos a la oficina encargada de proporcionar el material audiovisual de docencia con la siguiente solicitud: "Por favor, necesito para mañana a las ocho y media la sala 336 preparada para una clase con diapositivos". Esta sería una instrucción global, es decir, de lenguaje de alto nivel, que podría ser detallada (y de hecho va a ser detallada al ser llevada a la práctica) en una secuencia de instrucciones elementales que en "código de máquina" sería algo así como: "Por favor, mañana a las ocho diez saque la proyectora de dispositivos y llévela a la sala 336, baje el telón de proyección, tome la mesa alta que habitualmente se deja en el rincón y póngala en el pasillo central de la sala a unos cinco metros del telón, ponga la proyectora sobre la mesa apuntando hacia el telón, enchufe la proyectora, enciéndala, compruebe que la ampolleta funciona y que el haz de luz está bien encuadrada sobre el telón, apáguela, gracias".

De este ejemplo también resulta evidente que los adjetivos "global" y "detallada" son relativos. La primera instrucción podría ser incluso más concisa o global: "Por favor, le recuerdo que mañana tengo una clase", presuponiendo que el interlocutor sabe o puede averiguar dónde y a qué hora será la clase y subentenderá que necesitamos proyectar diapositivos. A su vez, la segunda versión, la que imita al código de máquina, puede ser mucho más detallada: en su forma actual presupone que el interlocutor sabe dónde se guarda la proyectora, o cómo ésta se enciende, o, por llevar el argumento al extremo, sabe cómo caminar.

Concordante con lo que ya hemos dicho sobre los computadores, tanto para los lenguajes de alto nivel como para las instrucciones elementales del código de máquina no existen ambigüedades sobre lo que es entendible o no: existe un conjunto claramente definido de instrucciones válidas, o sea, inteligibles para cada lenguaje. Obviamente, las instrucciones del lenguaje de alto nivel son mucho más "poderosas", es decir, cada una de ellas pone en juego una compleja secuencia de acciones elementales.

El lenguaje de alto nivel sin embargo no libera de rigurosidad y precisión: las reglas sintácticas del lenguaje usado deben respetarse cuidadosamente. No podemos pedirle al computador que entienda un comando con un error ortográfico por obvio que éste sea, ni menos que tome la decisión que mejor le parezca si surge una situación que nosotros no previmos. Los autómatas no perdonan errores porque no los entienden, ni toleran ambigüedades porque no saben qué hacer frente a ellas.


El sentido común

Al principiante suele resultarle molesta esta falta de "sentido común" característica de los computadores. ¿Cómo puede la máquina ser tan tonta que no entienda que si escribí PRIMT A se trata obviamente de un error tipográfico y que lo que quise decir fue PRINT A?. A poco de andar, sin embargo, uno se da cuenta que la carencia de sentido común es uno de los grandes méritos de la máquina, concretamente, cuando le pidamos cosas que no son las "habituales" pero que nosotros sabemos bien por qué las solicitamos. En tales casos la máquina cumplirá nuestras órdenes sin mostrar la menor perplejidad, a diferencia de lo que probablemente hubiera hecho un ser humano. Rápidamente uno aprende a apreciar esta obediencia y falta de crítica de los computadores, tal como en los humanos apreciamos las características diametralmente opuestas: la capacidad de criticar y plantear alternativas.


Como escribir un programa

Hacer que un computador resuelva un problema significa ni más ni menos que escribir un programa a ser ejecutado por ese computador. El primer paso es precisar muy claramente el problema a solucionar (Fig.4). Ejemplos: dada una lista de palabras producir otra lista conteniendo las mismas palabras pero en orden alfabético; dada una serie de pares de datos, es decir, de los valores que tenían dos variables dadas en determinados momentos, calcular e imprimir el número total de observaciones, los promedios, medianas y desviaciones estándards de cada una de las dos variables, el coeficiente de correlación entre ellas y producir un gráfico en que cada observación se represente como un punto del par de coordenadas.

Una vez que sabemos lo que queremos, el segundo paso consiste en escribir el algoritmo general para resolver el problema. En este momento no necesariamente estamos pensando en el computador en particular para quién eventualmente escribiremos el programa, sino más bién en la estrategia a seguir, en la secuencia de pasos lógicos que cualquier autómata o ser humano tendría que cumplir para resolver el problema que nos preocupa. Como ha dicho Wirth, un algoritmo general es "una pauta de conducta", una forma de comportamiento que garantiza la solución de un tipo de problemas.

Al pensar el algoritmo siempre tenemos presente dos tipo de elementos: datos (variables, números, palabras, etc.) y acciones a ejecutar sobre esos datos. Es útil al respecto imitar el formato habitual de las recetas de cocina que diferencian entre ingredientes y operaciones proporcionando primero una ordenada lista de los ingredientes y pasando enseguida a explicar lo que se hará con ellos. Análogamente, es recomendable encabezar un algoritmo (y un programa) con la explicitación de las variables: aquellas que se entrarán, aquellas que son los resultados finales que buscamos, y, si procede, variables auxiliares a utilizarse en etapas intermedias. Frecuentemente en nuestros problemas las variables no serán datos aislados sino serán una serie o una matriz de datos. En el primero de los ejemplos que dábamos recién, queremos a partir de la serie de palabras P1, P2, P3...... Pn crear la serie Q1 , Q2, Q3..... Qn, la cual contiene los mismos elementos pero ordenados de modo tal que Q1 precede alfabéticamente a Q2, Q2 a Q3, etc. A veces las variables tomarán forma de una matriz bidimensional (o multidimensional): por ejemplo si queremos que nuestra base de datos sea la temperatura registrada cada hora en cada día de un mes, definimos una matriz para las variables T (d, h) de 31 días por 24 horas donde 1 (5, 14) representa el valor de la temperatura a las 14 horas del día 5. La matriz tridimensional T(m, d, h) nos permitiría identificar el valor de cada hora, de cada día, de cada mes.


Diagrama de flujo

En cuanto a las acciones a cumplir, el formato habitual para expresarlas es el diagrama de flujo que nos permite visualizar el proceso de transformaciones que sufren los datos paso a paso. La acción fundamental en computación es la asignación de un valor a una variable. Frecuentemente a una variable se le reasignarán nuevos valores en el curso de la ejecución de un programa. Al principio de un programa es útil definir cada variable. Muchas de ellas serán "leídas" o "entradas" cada vez que se ejecute el programa, y habrán instrucciones apropiadas para preguntar por el valor de ellas al usuario en la consola u obtenerlas de un disco con datos, o de tarjetas. Otras variables tienen siempre un determinado valor al principio de la ejecución del programa, como en la Fig.3 la variable A siempre parte siendo igual a cero. Nótese que habitualmente los lenguajes de computación denotan la operación de asignación con el signo " = ", de donde tiene perfecto sentido la instrucción A = A + 4, que simplemente significa "asígnese a la variable A el valor que previamente tenía esta variable más cuatro", si A valía 323 ahora valdrá 327.

Los rombos en el diagrama de flujo indican decisiones. En ellos se postula una afirmación, si ésta se cumple se seguirá un camino, si no, otro. Una aplicación característica de ellos se da en la terminación de un "loop" o serie de reiteraciones de uno o más pasos. La Fig.3 ilustra un programa con un loop que se repetirá hasta que la condición B = 0 sea satisfecha.

Una última acotación: el programa de la fig.3 permite multiplicar dos números enteros mayores que 0. El algoritmo conduce al desastre si X = 2.5, ó X = -4, pues jamás se cumplirá la condición X = 0, pero eso no quita que sea perfectamente adecuado para multiplicar dos números naturales. El corolario es que un algoritmo es válido para un cierto rango o tipo de datos, y eso es mejor aclararlo de la partida. (Quizás sería incluso una buena idea introducir en el diagrama de la fig.3 un rombo después de la entrada de datos tal que si X no cumple las condiciones señaladas, el programa no pasa a la etapa siguiente).

Hecho el algoritmo general, el tercer paso es escribir el algoritmo particular, es decir, el programa, ya que el computador no entiende diagramas de flujo.

Respetando rigurosamente las reglas de sintaxis del lenguaje a usar, los pasos esbozados en el diagrama de flujo se expresan en instrucciones. Aquí sí que las características propias del computador a usar son relevantes. Por ejemplo, ocuparemos el "dialecto" propio del computador en cuestión (típicamente los microcomputadores usan BASIC y cada uno de ellos tiene sutiles diferencias). Si usamos una gran cantidad de datos nos preocuparemos que la memoria de la que disponemos nos alcance, trivialidad mundana que nos tenía sin cuidado al escribir el diagrama de flujo del algoritmo general. El programa terminado se entra al computador: en los microcomputadores desde una consola, en otros, habitualmente por tarjetas perforadas.

El cuarto y último paso previo a que el programa pueda ser ejecutado consiste en traducirlo a código de máquina. Afortunadamente esto no lo hace uno. En el caso de FORTRAN, PASCAL y otros hay un "compilador" que no es sino un programa proporcionado por el fabricante del computador que transforma las instrucciones del lenguaje de alto nivel en instrucciones del código de máquina. Es decir, primero el computador ejecuta un programa llamado compilador utilizando como datos de entrada el programa escrito en lenguaje de alto nivel y produciendo como resultado el programa en código de máquina. Posteriormente este programa podrá ejecutarse como tal. La idea es semejante con BASIC pero no son dos etapas consecutivas pues en vez de un compilador hay un intérprete que va traduciendo cada instrucción a lenguaje de máquina a medida que se va ejecutando el programa. Una tercera modalidad la constituyen los llamados "assembler" (ensambladores) en que uno escribe el programa con el detalle del código de máquina pero con ciertas facilidades propias de los lenguajes de alto nivel. En general es más engorroso escribir programas en assembler que en lenguaje con compilador, siendo el menos difícil el lenguaje con intérprete; pero por otra parte el ahorro en memoria ocupada por el programa y, considerando a veces muy importante, la rapidez de ejecución del programa, sigue ese mismo orden.

Aquí el problema termina y el programa está hecho. La verdad es que aquí los problemas comienzan pues el usuario, al intentar ejecutar el programa, se da cuenta de los errores conceptuales que ha cometido (y vuelve atrás a modificar el diagrama de flujo) o de los errores de sintaxis en la escritura del programa (y debe corregirlo). Como nuestro propósito es estimular al lector al uso de computadores y no el disuadirlo, no insistiremos en este aspecto.


RESUMEN:

Los computadores son autómatas capaces de ejecutar sólo un número reducido de operaciones muy simples. Su extraordinaria efectividad proviene de su confiabilidad y rapidez así como de su gran capacidad para almacenar datos e instrucciones en memoria. Solucionar un problema utilizando un computador significa escribir un programa para que éste lo ejecute. Las primeras etapas consisten en definir el problema y diseñar un algoritmo general. Posteriormente se escribe el programa mismo. Si se escribe en código de máquina, éste es directamente ejecutado. Igual cosa si se hace en un lenguaje que, como BASIC, se va interpretando a código de máquina al irse ejecutando. En lenguajes que usan compilador (FORTRAN, PASCAL) o ensamblador, el programa original es sometido a un paso previo al computador el que lo transforma en código de máquina para ser ejecutado.



Ennio A. Vivaldi V.

INTA Universidad de Chile.



Para saber más


1. Elementos de Computación. Jaime Michelow, Inés Harding. Edit. Universitaria, 277 págs., 1973.

2. Introducción a la Informática y los sistemas de información administrativos. Oscar Barros V., Antonio Holgado S.M., Víctor Pérez V. Edit. Universitaria, 147 págs., 1978.

3. Scientific American 237:3, septiembre 1977. (toda la revista).

4. Systematic Programming: an Introduction Niklaus Wirth. Prentice-Hall, 1973.

5. The Arts of Electronic. P. Horowitz, W. Hill, Cambridge University Press, 1980 (capítulos 8 al 11).


0 Respuestas

Deje una respuesta

Su dirección de correo electrónico no será publicada. Los campos obligatorios están marcados.*

Buscar



Recibe los artículos en tu correo.

Le enviaremos las últimas noticias directamente en su bandeja de entrada